package cn.slipi.common.handler;

import cn.slipi.common.enums.ResponseCode;
import cn.slipi.common.exception.BizException;
import cn.slipi.common.response.ErrorResponse;
import cn.slipi.common.utils.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * lee
 * 缺陷：url错误导致的404异常无法捕捉，虽然可用配置404抛出异常但不建议这么做
 */
@Slf4j
//@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ErrorResponse throwableHandler(Throwable e, HttpServletRequest hsr) {
        ErrorResponse error = ErrorResponse.error(ResponseCode.SYSTEM_ERROR, e);
        log.error("URL:{},系统异常！", hsr.getRequestURI(), e);
        return error;
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse noHandlerFoundHandler(Throwable e, HttpServletRequest hsr) {
        ErrorResponse error = ErrorResponse.error(ResponseCode.NOT_FOUND, e);
        log.error("URL:{},请求不存在！", hsr.getRequestURI(), e);
        return error;
    }

    @ExceptionHandler(BizException.class)
    public ErrorResponse bizHandler(BizException e, HttpServletRequest hsr) {
        ErrorResponse error = ErrorResponse.builder().code(e.getCode()).msg(e.getMsg()).exception(e.getClass().getName()).build();
        log.warn("URL:{},业务异常：{}", hsr.getRequestURI(), error);
        return error;
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ErrorResponse validateHandler(MethodArgumentNotValidException e, HttpServletRequest hsr) {
        String fieldInfo = this.getFieldInfo(e.getBindingResult().getFieldErrors());
        ErrorResponse error = ErrorResponse.error(ResponseCode.PARAM_IS_INVALID, e, fieldInfo);
        log.warn("URL:{},参数校验异常：{}", hsr.getRequestURI(), error);
        return error;
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public ErrorResponse illegalArgumentException(IllegalArgumentException e, HttpServletRequest request) {
        ErrorResponse error = ErrorResponse.builder().code(400)
                .msg(e.getMessage())
                .exception(e.getClass().getName())
                .build();
        log.warn("URL:{} ,业务校验异常:{}", request.getRequestURI(), e);
        return error;
    }

    /**
     * 处理validate参数校验异常
     *
     * @param fieldErrors
     * @return
     */
    private String getFieldInfo(List<FieldError> fieldErrors) {
        List<Map<String, String>> info = new ArrayList<>();
        for (FieldError obj : fieldErrors) {
            Map<String, String> single = new HashMap<>();
            single.put(obj.getField(), obj.getDefaultMessage());
            info.add(single);
        }
        return JsonUtil.object2Json(info);
    }

}
